package com.dc.web.controller;

import com.dc.constant.Constants;
import com.dc.constant.MessageConstant;
import com.dc.dao.ConfigDao;
import com.dc.dao.EnergyCompanyDao;
import com.dc.dao.EnergyMonitorDao;
import com.dc.entity.ConfigEntity;
import com.dc.entity.EnergyCompanyEntity;
import com.dc.entity.EnergyMonitorEntity;
import com.dc.exception.ServiceException;
import com.dc.model.*;
import com.dc.service.EnergyMonitorService;
import com.dc.service.dto.CMonitorChildDto;
import com.dc.utils.DateUtils;
import io.swagger.annotations.ApiOperation;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.data.domain.Example;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 内部监控、碳核查
 */
@RestController
@RequestMapping("/api/energy_monitor")
@Slf4j
public class EnergyMonitorController {

    @Resource
    EnergyMonitorDao energyMonitorDao;

    @Resource
    EnergyCompanyDao energyCompanyDao;

    @Resource
    EnergyMonitorService energyMonitorService;

    @Resource
    private ConfigDao configDao;

    /**
     * 查询表格数据
     * @param energyMonitorBody
     * @return
     */
    @GetMapping("/list")
    public AjaxResult list(@Validated EnergyMonitorSearchBody energyMonitorBody) {

        List<EnergyMonitorChildBody> commonEnergyMonitor = energyMonitorService.getEnergyMonitor(energyMonitorBody);

        return AjaxResult.success(commonEnergyMonitor);
    }

    /**
     * 查询表格数据, 有时间区间
     * @param param
     * @return
     *
     */
    @GetMapping("/list2")
    public AjaxResult list(@Validated EnergyMonitorSearchTimeBetweenBody param) {

        String company = param.getCompany();
        Integer type = param.getType();

        EnergyMonitorSearchTimeBetweenBody body = calcParams(param);

        int beginYear = DateUtils.getYear(body.getBeginTime());
        int endYear = DateUtils.getYear(body.getEndTime());

        List<EnergyMonitorBody> commonEnergyMonitor = new ArrayList<>();

        for(int i = beginYear; i <= endYear; i++) {
            EnergyMonitorSearchBody energyMonitorBody = new EnergyMonitorSearchBody();
            energyMonitorBody.setCompany(company);
            energyMonitorBody.setType(body.getType());
            energyMonitorBody.setYear(i);
            List<EnergyMonitorChildBody> energyMonitor = energyMonitorService.getEnergyMonitor(energyMonitorBody);

            EnergyMonitorBody monitorBody = new EnergyMonitorBody();
            monitorBody.setCompany(company);
            monitorBody.setType(type);
            monitorBody.setYear(i);
            monitorBody.setList(energyMonitor);

            commonEnergyMonitor.add(monitorBody);
        }

        return AjaxResult.success(commonEnergyMonitor);
    }

    /**
     * 参数处理
     * 如果我传了startTime 或 endTime，以具体时间为准。
     *   否则就按year为准。
     *   如果没给你year，也没有startTime和endTime，那你取系统当前年份当year。
     *
     * @param body
     * @return
     */
    public EnergyMonitorSearchTimeBetweenBody calcParams(EnergyMonitorSearchTimeBetweenBody body) {

        Date beginTime = body.getBeginTime();
        Date endTime = body.getEndTime();

        if(ObjectUtils.isNotEmpty(beginTime) && ObjectUtils.isNotEmpty(endTime)) {
            if(DateUtils.differentDaysDoubleByMillisecond(beginTime, endTime) < 0) {    // 结束时间大于开始时间，抛出异常
                throw new ServiceException(MessageConstant.ERR_ENDTIME_LT_BEGINTIME);
            }
        } else if(ObjectUtils.isNotEmpty(beginTime) && ObjectUtils.isEmpty(endTime)) {  // 开始时间不为空，结束时间为空
            body.setEndTime(new Date());
        } else if(ObjectUtils.isEmpty(beginTime) && ObjectUtils.isNotEmpty(endTime)) {  // 开始时间为空，结束时间不为空
            EnergyCompanyEntity minEntity = energyCompanyDao.findTop1ByCompanyAndTypeOrderByYearAsc(body.getCompany(), body.getType());
            if(ObjectUtils.isEmpty(minEntity)) {        // 数据库中没有 company type 的数据，则直接将 beginTime 设置为 endTime， 避免不必要的循环
                body.setBeginTime(endTime);
            } else {
                Integer minYear = minEntity.getYear();
                body.setBeginTime(DateUtils.dateTime(DateUtils.YYYY_MM, minYear + "-01"));
            }
        } else {                                                                        // 两个时间都为空
            Integer year = body.getYear();
            if(ObjectUtils.isEmpty(year)) {                                                     // year 为空 ， 取当前时间
                year = Calendar.getInstance().get(Calendar.YEAR);
            }
            body.setBeginTime(DateUtils.dateTime(DateUtils.YYYY_MM,  year + "-01"));
            body.setEndTime(DateUtils.dateTime(DateUtils.YYYY_MM, year + "-12"));
        }

        return body;
    }

    /**
     * 新增/更新
     * @param energyMonitorBody
     * @return
     */
    @PostMapping()
    public AjaxResult insertOrUpdate(@RequestBody EnergyMonitorBody energyMonitorBody) {

        List<EnergyMonitorChildBody> list = energyMonitorService.insertOrUpdate(energyMonitorBody);

        return AjaxResult.success(list);
    }

    /**
     * 计算实物量  孖洲岛  碳排放指标完成率
     *        碳排放量(深圳指南）(合计) / 碳排放量月度/年度指标(合计)
     *        碳排放强度-深圳指南
     */
    @ApiOperation("内部监控-孖洲岛指标完成率-碳排放强度监控")
    @GetMapping("/c_complete_rate_quote")
    public AjaxResult getCCompleteRateAndCQUote(Integer year) {

        if(ObjectUtils.isEmpty(year)) {
            year = DateUtils.getYear();
        }

        EnergyMonitorSearchBody energyMonitorBody = new EnergyMonitorSearchBody();
        energyMonitorBody.setCompany(Constants.NAME_COMPANY_ZIZHOU);
        energyMonitorBody.setYear(year);
        energyMonitorBody.setType(Constants.TYPE_DC_IN_MONITOR);

        Map<String, Object> result = new HashMap<>();

        List<CMonitorChildDto> cMonitorList = energyMonitorService.getCMonitor(energyMonitorBody);

        if(ObjectUtils.isEmpty(cMonitorList)) {
            return AjaxResult.success(result);
        }

        CMonitorChildDto shenzhenCZhinan = null;        // 碳排放量-深圳指南
        CMonitorChildDto shenzhenCFlag = null;          // 碳排放量月度/年度指标
        CMonitorChildDto shenzhenCQuote = null;         // 碳排放强度-深圳指南

        for(CMonitorChildDto dto : cMonitorList) {
            String name = dto.getName();
            if(Constants.NAME_C_SHENZHEN_INCLUDE.equals(name)) {
                shenzhenCZhinan = dto;
            } else if(Constants.NAME_C_FLAG_INCLUDE.equals(name)) {
                shenzhenCFlag = dto;
            } else if(Constants.NAME_C_POWER_INCLUDE.equals(name)) {
                shenzhenCQuote = dto;
            }
        }

        Double cCompleteRate = shenzhenCZhinan.getSum() / shenzhenCFlag.getSum();
        if(Double.isNaN(cCompleteRate)) {
            cCompleteRate = 0.;
        }

        ConfigEntity cPowerFlagIncludeConfig = configDao.findByYearAndName(year, Constants.NAME_C_POWER_FLAG_INCLUDE);

        Double cPowerFlagInclude = 0.;
        if(ObjectUtils.isNotEmpty(cPowerFlagIncludeConfig)) {
            cPowerFlagInclude = cPowerFlagIncludeConfig.getValue();
        }


        result.put(Constants.KEY_C_COMPLETE_RATE, cCompleteRate);
        result.put(Constants.NAME_C_POWER_INCLUDE, shenzhenCQuote);
        result.put(Constants.NAME_C_POWER_FLAG_INCLUDE_KEY, cPowerFlagInclude);

        return AjaxResult.success(result);
    }

    private Double calcCComplateRate(EnergyMonitorSearchBody body) {

        List<CMonitorChildDto> monitor = energyMonitorService.getCMonitor(body);

        if(ObjectUtils.isEmpty(monitor)) {
            return 0.;
        }
        for (CMonitorChildDto dto : monitor) {
            String dtoName = dto.getName();
            if(Constants.NAME_C_SHENZHEN_INCLUDE.equals(dtoName)) {
                Double used = dto.getSum();
                ConfigEntity config = null;
                if (Constants.NAME_COMPANY_YOU.equals(body.getCompany())) {
                    config = configDao.findByYearAndName(body.getYear(), Constants.NAME_C_CHECK_QUOTA_SHENZHEN_YOU);     // 没有配置返回 0
                } else if (Constants.NAME_COMPANY_ZHAO.equals(body.getCompany())) {
                    config = configDao.findByYearAndName(body.getYear(), Constants.NAME_C_CHECK_QUOTA_SHENZHEN_ZHAO);    // 没有配置返回 0
                } else if (Constants.NAME_COMPANY_ZIZHOU.equals(body.getCompany())) {
                    config = configDao.findByYearAndName(body.getYear(), Constants.NAME_C_CHECK_QUOTA_SHENZHEN_ZI);      // 没有配置返回 0
                }

                if(ObjectUtils.isEmpty(config)) {
                    log.warn("公司: " + body.getCompany() + " 缺少配置 " + Constants.NAME_C_SHENZHEN_INCLUDE);
                    return 0.;
                }

                return used / config.getValue();
            }
        }

        return 0.;
    }

    /**
     * 碳配额完成率   =   碳排放量-深圳指南  /  深圳市碳配额
     * @return
     */
    @ApiOperation("碳核查-碳配额完成率")
    @GetMapping("/c_quota_complete_rate")
    public AjaxResult cQuotaCompleteRate() {

        List<Double> result = new ArrayList<>();

        int year = DateUtils.getYear();
        int type = Constants.TYPE_DC_C_CHECK;

        EnergyMonitorSearchBody youMonitorBody = new EnergyMonitorSearchBody(Constants.NAME_COMPANY_YOU, type, year);
        result.add(calcCComplateRate(youMonitorBody));

        EnergyMonitorSearchBody zhaoMonitorBody = new EnergyMonitorSearchBody(Constants.NAME_COMPANY_ZHAO, type, year);
        result.add(calcCComplateRate(zhaoMonitorBody));

        EnergyMonitorSearchBody zizhouMonitorBody = new EnergyMonitorSearchBody(Constants.NAME_COMPANY_ZIZHOU, type, year);
        result.add(calcCComplateRate(zizhouMonitorBody));

        return AjaxResult.success(result);
    }

}
